package com.lz.virtualthread.common.utils.http;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.lz.virtualthread.common.constant.HttpStatus;
import com.lz.virtualthread.common.domain.ResponseVo;
import com.lz.virtualthread.common.utils.DataMap;
import com.lz.virtualthread.common.utils.DateUtils;
import com.lz.virtualthread.common.utils.SysUtils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;
import java.util.concurrent.TimeUnit;

@Slf4j
public class OkHttpUtil {
    private static OkHttpClient client = new OkHttpClient().newBuilder()
            .callTimeout(600, TimeUnit.SECONDS)
            .connectTimeout(600, TimeUnit.SECONDS)
            .readTimeout(600, TimeUnit.SECONDS)
            .build();

    public static byte[] getBytes(String url) {
        Response execute = null;
        Request request = new Request.Builder()
                .method("GET", null)
                .url(url)
                .build();
        try {
            execute = client.newCall(request).execute();
            if (ObjectUtil.isNotNull(execute) && execute.isSuccessful()) {
                return execute.body().bytes();
            }
        } catch (IOException e) {
            log.error("http get 请求失败--{}", e);
        }
        return null;
    }

    /**
     * POST请求
     */
    public static String requestPost(SstInf sstInf) {
        Response execute = null;
        String resp = null;
        long start = 0;
        long end = 0;
        try {
            //Header
            String method = SysUtils.isNotVoid(sstInf.getInfMethod()) ? sstInf.getInfMethod() : "POST";
            String authorization = SysUtils.isNotVoid(sstInf.getAuthorization()) ? sstInf.getAuthorization() : (SysUtils.isNotVoid(DataMap.get(sstInf.getInfRealEnv())) ? DataMap.get(sstInf.getInfRealEnv()).toString() : "");
            String cookie = SysUtils.isNotVoid(sstInf.getCookie()) ? sstInf.getCookie() : (SysUtils.isNotVoid(DataMap.get(sstInf.getInfRealEnv())) ? "uToken=" + DataMap.get(sstInf.getInfRealEnv()).toString() : "");

            if (sstInf.getInfProperty() != null && sstInf.getInfProperty().equalsIgnoreCase("login")) {
                authorization = "";
                cookie = "";
            }

            //拼装requestBody
            RequestBody requestBody = RequestBody.create(sstInf.getInfRequest(),
                    MediaType.get(SysUtils.isNotVoid(sstInf.getContentType()) ? sstInf.getContentType() : "application/json"));
            //拼装Request
            Request request = new Request.Builder()
                    .method(method, requestBody)
                    .addHeader("Authorization", authorization)
                    .addHeader("Cookie", cookie)
                    .addHeader("noLogin", SysUtils.isNotVoid(sstInf.getNoLogin()) ? sstInf.getNoLogin() : "0")
                    .addHeader("inner", SysUtils.isNotVoid(sstInf.getInfInner()) ? sstInf.getInfInner() : "0")
                    .url(sstInf.getInfFullUrl())
                    .build();
            start = System.currentTimeMillis();
            sstInf.setRequestTime(DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS_SSS());
            Call call = client.newCall(request);
            //设置超时时间，当接口中保存的为准，如果没有保存的，取系统配置的超时时间
            call.timeout().timeout(SysUtils.isVoid(sstInf.getTimeOut()) ? 300 : Long.valueOf(sstInf.getTimeOut()), TimeUnit.MILLISECONDS);
            execute = call.execute();

            end = System.currentTimeMillis();
            sstInf.setResponseTime(DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS_SSS());
            sstInf.setConsumeTime(end - start);
            if (ObjectUtil.isNotNull(execute) && execute.isSuccessful() && SysUtils.isNotVoid(execute.body())) {
                return execute.body().string();
            }
        } catch (InterruptedIOException e) {
            //处理超时
            end = System.currentTimeMillis();
            sstInf.setConsumeTime(end - start);
            ResponseVo res = ResponseVo.failure("请求超过预定超时时间", HttpStatus.TIME_OUT);
            resp = JSONUtil.toJsonStr(res);
            log.error("okhttp POST请求超时--{}", e);
        } catch (IOException e) {
            end = System.currentTimeMillis();
            sstInf.setConsumeTime(end - start);
            resp = e.getMessage();
            e.printStackTrace();
            log.error("okhttp POST请求失败--{}", e);
        }
        return resp;
    }


    public static String requestGet(SstInf sstInf) {
        Response execute = null;
        String resp = null;
        long start = 0;
        long end = 0;
        try {
            //Header
            String infRequest = SysUtils.isNotVoid(sstInf.getInfRequest()) ? sstInf.getInfRequest() : null;
            String method = "GET";
            //拼装GET参数和URL
            String url = sstInf.getInfFullUrl();
            StringBuffer sb = new StringBuffer();
            sb.append(url);

            if (SysUtils.isNotVoid(infRequest)) {
                sb.append("?");
                Map<String, String> map = JSONUtil.toBean(infRequest, HashMap.class);
                StringJoiner param = new StringJoiner("&");
                for (Map.Entry entry : map.entrySet()) {
                    param.add(entry.getKey() + "=" + entry.getValue());
                }
                sb.append(param);

            }
            //拼装 request
            Request request = new Request.Builder()
                    .url(sb.toString())
                    .method(method, null)
                    .addHeader("Content-Type", "application/json")
                    .build();
            //请求
            start = System.currentTimeMillis();
            Call call = client.newCall(request);
            //设置超时时间，当接口中保存的为准，如果没有保存的，取系统配置的超时时间
            call.timeout().timeout(3000, TimeUnit.MILLISECONDS);
            execute = call.execute();
            end = System.currentTimeMillis();
            //返回结果
            if (ObjectUtil.isNotNull(execute) && execute.isSuccessful() && SysUtils.isNotVoid(execute.body())) {
                return execute.body().string();
            }
        } catch (InterruptedIOException e) {
            //处理超时
            end = System.currentTimeMillis();
            sstInf.setConsumeTime(end - start);
            ResponseVo res = ResponseVo.failure("请求超过预定超时时间", HttpStatus.TIME_OUT);
            resp = JSONUtil.toJsonStr(res);
            log.error("okhttp POST请求超时--{}", e);
        } catch (IOException e) {
            end = System.currentTimeMillis();
            resp = e.getMessage();
            e.printStackTrace();
            log.error("okhttp 请求失败--{}", e);
        }
        sstInf.setConsumeTime(end - start);
        return resp;
    }

    /**
     * get请求通用
     * address: ip地址
     * api: 接口路径、
     * map: 传递数据
     */
    public static ResponseVo requestGetCommon(String address, String api, Map<String, Object> map) {
        Response execute = null;
        ResponseVo responseVo = new ResponseVo();

        try {
            //Header
            String method = "GET";

            //拼装GET参数和URL
            StringBuffer sb = new StringBuffer();
            sb.append(address + api);
            sb.append("?");
            if (map != null && map.keySet().size() > 0) {
                StringJoiner param = new StringJoiner("&");
                for (Map.Entry entry : map.entrySet()) {
                    param.add(entry.getKey() + "=" + entry.getValue());
                }
                sb.append(param);
            }
            //拼装 request
            Request request = new Request.Builder()
                    .url(sb.toString())
                    .method(method, null)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Authorization", null)
                    .addHeader("Cookie", null)
                    //.addHeader("inner", "1")
                    .build();
            //请求
            Call call = client.newCall(request);
            execute = call.execute();
            //返回结果
            if (ObjectUtil.isNotNull(execute) && execute.isSuccessful() && SysUtils.isNotVoid(execute.body())) {
                return ResponseVo.success(execute.body().string());
            } else {
                return ResponseVo.failure("请求失败!,状态码:" + execute.code());
            }
        } catch (IOException e) {
            log.error("okhttp 请求失败--{}", e);
            return ResponseVo.failure(e.getMessage());
        }
    }

    /**
     * POST请求通用
     * address: ip地址
     * api: 接口路径、
     * map: 传递数据
     */
    public static ResponseVo requestPostCommon(String address, String api, Map<String, Object> map) {
        Response execute = null;
        ResponseVo responseVo = new ResponseVo();
        try {
            //Header
            String method = "POST";

            //拼装requestBody
            RequestBody requestBody = RequestBody.create(JSONObject.toJSONString(map), MediaType.get("application/json"));
            //拼装Request
            Request request = new Request.Builder()
                    .method(method, requestBody)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Authorization", null)
                    .addHeader("Cookie", null)
                    //.addHeader("inner", "1")
                    .url(address + api)
                    .build();
            execute = client.newCall(request).execute();
            if (ObjectUtil.isNotNull(execute) && execute.isSuccessful() && SysUtils.isNotVoid(execute.body())) {
                return ResponseVo.success(execute.body().string());
            } else {
                return ResponseVo.failure(execute.code());
            }
        } catch (IOException e) {
            log.error("okhttp POST请求失败--{}", e);
            return ResponseVo.failure(e.getMessage());
        }
    }
}
